﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Collections; //bruges til enumerator
using System.Runtime.Serialization.Formatters.Binary; //Namespace til serialisering
using System.IO; //Namespace til input/output, bruges til at streaming af fil for serialisering

using Model;
using Interfaces;
using System.Data.SqlClient;
using Indstillinger;

namespace Controller
{
    [Serializable]
    public class LagerSystem
    {
        //Attributter
        private LeverandørCollection leverandørCol;
        private ProduktCollection produktCol;
        
        //Session attributter
        [NonSerialized] private Produkt nuværendeProdukt;
        [NonSerialized] private Leverandør nuværendeLeverandør;

        //Konstant
        private const string DATAFIL = "systemdata.bin";

        //Kontruktør
        public LagerSystem()
        {
            leverandørCol = new LeverandørCollection();
            produktCol = new ProduktCollection();
        }

        ////Metoder
        //Tilføjer en leverandør til systemet
        public void RegistrerLeverandør(string navn, string adresse, string postnr, string by, string tlfnr, string www, string email, string kontaktPerson)
        {
            leverandørCol.RegistrerLeverandør(navn, adresse, postnr, by, tlfnr, www, email, kontaktPerson);

            gemData();
        }

        //Starter en session for leverandør og returnere et leverandør interface ud fra et leverandørId
        public ILeverandørdata FindLeverandør(int leverandørId)
        {
            nuværendeLeverandør = leverandørCol.FindLeverandør(leverandørId);
            if (nuværendeLeverandør != null)
                return nuværendeLeverandør;

            nuværendeLeverandør = new Leverandør(leverandørId, null, null, null, null, null, null, null, null);
            leverandørCol.TilføjLeverandør(nuværendeLeverandør);
           
            return nuværendeLeverandør;
        }

        //Redigere leverandør oplysninger
        public void RedigerLeverandør(string navn, string adresse, string postnr, string by, string tlfnr, string www, string email, string kontaktPerson)
        {
            nuværendeLeverandør.Rediger(navn, adresse, postnr, by, tlfnr, www, email, kontaktPerson);

            //gemData();
        }

        //Returnerer en iterator over leverandørlisten
        public IEnumerator<ILeverandørdata> GetLeverandøriterator()
        {
            return leverandørCol.GetLeverandøriterator();
        }

        //Tilføjer et produkt til systemet
        public void OpretProdukt(int leverandørId, string produktNr, string betegnelse, int stkPrPakke, int beholdning, int minimumBeholdning, double pakkePris)
        {

            Leverandør leverandør = leverandørCol.FindLeverandør(leverandørId);
            if (leverandør == null)
            {
                leverandør = new Leverandør(leverandørId, null, null, null, null, null, null, null, null);
                leverandørCol.TilføjLeverandør(leverandør);
            }

            produktCol.OpretProdukt(produktNr, betegnelse, stkPrPakke, beholdning, minimumBeholdning, pakkePris, leverandør);
        }

        //Starter en session for produkt og returnere et produkt interface ud fra et produktNr
        public IProduktdata FindProdukt(string produktNr)
        {
            nuværendeProdukt = produktCol.FindProduktIModel(produktNr);
            if (nuværendeProdukt != null)
                return nuværendeProdukt;

            SqlConnection con = new SqlConnection(DbIndstillinger.HentConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = con;
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
            cmd.CommandText = "hentEtProdukt";
            con.Open();
            cmd.Parameters.Add("@produktNr", System.Data.SqlDbType.NVarChar).Value = produktNr;
            SqlDataReader reader = cmd.ExecuteReader();

            if (!reader.Read())
                nuværendeProdukt = null;
            else
            {
                int leverandørId = (int)reader["leverandørId"];
                Leverandør leverandør = (Leverandør)FindLeverandør(leverandørId);
                if (leverandør == null)
                {
                    leverandør = new Leverandør(leverandørId, null, null, null, null, null, null, null, null);
                    leverandørCol.TilføjLeverandør(leverandør);
                }
                nuværendeProdukt = new Produkt(produktNr, null, -1, -1, -1, -1, leverandør);
                produktCol.AddProdukt(nuværendeProdukt);
            }
            
            con.Close();

            return nuværendeProdukt;
        }

        //Nedskriver et produkt og returnere et produkt interface hvis minumums beholdning er nået, ellers returnere den null
        public IProduktdata HentProdukt(string produktNr)
        {
            Produkt produkt = produktCol.NedskrivBeholdning(produktNr);

            //gemData();

            return produkt;
        }

        //Tilføjer beholdning til session produkt
        public void OpskrivBeholdning(int antal)
        {
            nuværendeProdukt.OpskrivBeholdning(antal);

            gemData();
        }

        public IEnumerator GetProduktOversigtDB()
        {
            SqlConnection con = new SqlConnection(DbIndstillinger.HentConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = con;
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
            cmd.CommandText = "hentProduktOversigt";
            con.Open();

            SqlDataReader reader = cmd.ExecuteReader();

            List<IProduktdata> produkter = new List<IProduktdata>();
            while (reader.Read())
            {
                Produkt produkt = new Produkt(string.Empty, (string)reader["betegnelse"], (int)reader["stkPrPakke"], (int)reader["beholdning"], 0, (double)reader["pakkePris"], null);
                produkter.Add(produkt);
            }

            reader.Close();
            con.Close();

            return produkter.GetEnumerator();
        }

        //Returnerer en iterator over produktlisten //Gammel
        public IEnumerator GetProduktIterator()
        {
            return produktCol.GetProduktIterator();
        }

        public IEnumerator<IProduktdata> GetProdukterUnderMinimumsBeholdning()
        {
            SqlConnection con = new SqlConnection(DbIndstillinger.HentConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = con;
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
            cmd.CommandText = "findVarerUnderMinBeholdning";
            con.Open();

            SqlDataReader reader = cmd.ExecuteReader();

            List<IProduktdata> produkter = new List<IProduktdata>();
            while (reader.Read())
            {
                int levId = (int)reader["leverandørId"];
                Leverandør leverandør = leverandørCol.FindLeverandør(levId);

                if (leverandør == null)
                {
                    leverandør = new Leverandør(levId, null, null, null, null, null, null, null, null);
                    leverandørCol.TilføjLeverandør(leverandør);
                }

                Produkt produkt = new Produkt((string)reader["produktnr"], (string)reader["betegnelse"], (int)reader["stkPrPakke"], (int)reader["beholdning"], (int)reader["minimumsBeholdning"], (double)reader["pakkePris"], leverandør);
                produkter.Add(produkt);
            }

            reader.Close();
            con.Close();

            return produkter.GetEnumerator();
        }

        //Redigere produkt oplysninger
        public void RedigerProdukt(string produktNr, string betegnelse, int stkPrPakke, int beholdning, int minimumBeholdning, double pakkePris, int leverandørId)
        {
            Leverandør leverandør = leverandørCol.FindLeverandør(leverandørId);
            if (leverandør == null)
            {
                leverandør = new Leverandør(leverandørId, null, null, null, null, null, null, null, null);
                leverandørCol.TilføjLeverandør(leverandør);
            }

            nuværendeProdukt.Rediger(produktNr, betegnelse, stkPrPakke, beholdning, minimumBeholdning, pakkePris, leverandør);
        }

        //Slet aktuelt produkt
        public void SletProdukt()
        {
            produktCol.SletProdukt(nuværendeProdukt);
            gemData();
        }

        ////Persistens
        //Serialiser og gem data
        private void gemData()
        {
            //Skab fil til skrivning
            FileStream fileStream = new FileStream(DATAFIL, FileMode.Create, FileAccess.Write);

            //Formatter til object serialisering skabes
            BinaryFormatter binFormatter = new BinaryFormatter();

            //Serialiser LagerSystem (object af denne klasse + underelementer)
            binFormatter.Serialize(fileStream, this);

            fileStream.Close();
        }

        //Hent serialiseret data
        public static LagerSystem HentData()
        {
            FileStream fileStream = null;

            try
            {
                //Henter serialiseret data fra fil hvis fil findes
                fileStream = new FileStream(DATAFIL, FileMode.Open, FileAccess.Read);
            }
            catch (Exception)
            {
                //Hvis filen ikke findes lukkes stream og exception sendes tilbage
                fileStream.Close();
                throw;
            }

            BinaryFormatter binFormatter = new BinaryFormatter();

            //Deserialisere data fra fileStream
            LagerSystem lagerSystem = (LagerSystem)binFormatter.Deserialize(fileStream);

            fileStream.Close();

            return lagerSystem;
        }

        public List<dtoProduktForbrug> GetForbrugsProdukter(DateTime start, DateTime end)
        {
            SqlConnection con = new SqlConnection(DbIndstillinger.HentConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = con;
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
            cmd.CommandText = "findForbrug";
            con.Open();

            cmd.Parameters.Add("@startDato", System.Data.SqlDbType.DateTime).Value = start;
            cmd.Parameters.Add("@slutDato", System.Data.SqlDbType.DateTime).Value = end;

            SqlDataReader reader = cmd.ExecuteReader();

            List<dtoProduktForbrug> produkter = new List<dtoProduktForbrug>();
            while (reader.Read())
            {
                dtoProduktForbrug produkt = new dtoProduktForbrug((string)reader["betegnelse"], (int)reader["Antal"], (double)reader["Udgift"]);

                produkter.Add(produkt);
            }

            reader.Close();
            con.Close();

            return produkter;
        }
    }
}
